import type { Node, Edge } from "reactflow"
import type { NodeConfig } from "./node-configs"

export interface LayeredCode {
  layer: string
  title: string
  description: string
  code: string
  color: string
}

export interface GeneratedLangGraphCode {
  fullCode: string
  layers: LayeredCode[]
  summary: {
    nodeCount: number
    edgeCount: number
    layers: string[]
  }
}

/**
 * LangGraph 分层代码生成器
 * 根据节点和边生成符合6层架构的 LangGraph 代码
 */
export class LangGraphCodeGenerator {
  private nodes: Node[]
  private edges: Edge[]
  private nodeConfigs: Map<string, NodeConfig>

  constructor(nodes: Node[], edges: Edge[], nodeConfigs: NodeConfig[]) {
    this.nodes = nodes
    this.edges = edges
    this.nodeConfigs = new Map(nodeConfigs.map((c) => [c.type, c]))
  }

  /**
   * 生成完整的分层代码
   */
  generate(): GeneratedLangGraphCode {
    const layers: LayeredCode[] = []

    // Layer 1: 用户接入层（前端已实现，这里生成注释说明）
    layers.push(this.generateLayer1())

    // Layer 2: FastAPI 服务层
    layers.push(this.generateLayer2())

    // Layer 3: Agent 管理层
    layers.push(this.generateLayer3())

    // Layer 4: Agent 执行层（核心工作流代码）
    layers.push(this.generateLayer4())

    // Layer 5: 工具与集成层
    layers.push(this.generateLayer5())

    // Layer 6: 基础设施层
    layers.push(this.generateLayer6())

    // 生成完整代码
    const fullCode = this.generateFullCode(layers)

    return {
      fullCode,
      layers,
      summary: {
        nodeCount: this.nodes.length,
        edgeCount: this.edges.length,
        layers: layers.map((l) => l.layer),
      },
    }
  }

  private generateLayer1(): LayeredCode {
    return {
      layer: "Layer 1",
      title: "用户接入层 (User Interface Layer)",
      description: "Web界面、REST API、命令行工具",
      color: "#e3f2fd",
      code: `# Layer 1: 用户接入层
# 此层由前端 React 应用实现，提供可视化界面
# 用户通过拖拽节点、配置参数来构建工作流
#
# 主要组件：
# - Web前端: React + TypeScript + ReactFlow
# - REST API: 与 FastAPI 服务层通信
# - 实时预览: 工作流可视化展示

# 前端调用示例:
# POST /api/agents/execute
# {
#   "workflow_id": "${this.generateWorkflowId()}",
#   "input": {"user_query": "分析这个问题"},
#   "config": {...}
# }`,
    }
  }

  private generateLayer2(): LayeredCode {
    return {
      layer: "Layer 2",
      title: "FastAPI 服务层 (API Service Layer)",
      description: "路由层、中间件、服务层",
      color: "#f3e5f5",
      code: `# Layer 2: FastAPI 服务层
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
from typing import Dict, Any, Optional
import logging

# 配置日志
logger = logging.getLogger(__name__)

# 请求/响应模型
class WorkflowExecuteRequest(BaseModel):
    workflow_id: str
    input: Dict[str, Any]
    config: Optional[Dict[str, Any]] = None

class WorkflowExecuteResponse(BaseModel):
    success: bool
    result: Any
    metadata: Dict[str, Any]

# FastAPI 路由
app = FastAPI(title="${this.generateWorkflowId()} API")

@app.post("/api/workflows/execute", response_model=WorkflowExecuteResponse)
async def execute_workflow(request: WorkflowExecuteRequest):
    """执行工作流"""
    try:
        logger.info(f"Executing workflow: {request.workflow_id}")

        # 调用 Agent 管理层
        result = await agent_manager.execute(
            workflow_id=request.workflow_id,
            input_data=request.input,
            config=request.config
        )

        return WorkflowExecuteResponse(
            success=True,
            result=result,
            metadata={"workflow_id": request.workflow_id}
        )
    except Exception as e:
        logger.error(f"Workflow execution failed: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))

# 中间件配置
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)`,
    }
  }

  private generateLayer3(): LayeredCode {
    return {
      layer: "Layer 3",
      title: "Agent 管理层 (Agent Management Layer)",
      description: "Agent管理器、通信管理器、并发管理器",
      color: "#e8f5e8",
      code: `# Layer 3: Agent 管理层
from typing import Dict, Any, List
from datetime import datetime
import asyncio

class AgentManager:
    """Agent 生命周期管理器"""

    def __init__(self):
        self.agents: Dict[str, Any] = {}
        self.execution_history: List[Dict] = []

    async def execute(
        self,
        workflow_id: str,
        input_data: Dict[str, Any],
        config: Optional[Dict[str, Any]] = None
    ) -> Any:
        """执行 Agent 工作流"""

        # 1. 验证工作流配置
        workflow_config = self.validate_workflow(workflow_id)

        # 2. 初始化执行上下文
        context = ExecutionContext(
            workflow_id=workflow_id,
            input_data=input_data,
            config=config or {},
            timestamp=datetime.now()
        )

        # 3. 创建或获取 Agent 实例
        agent = await self.get_or_create_agent(workflow_id, workflow_config)

        # 4. 执行工作流
        result = await agent.run(context)

        # 5. 记录执行历史
        self.execution_history.append({
            "workflow_id": workflow_id,
            "timestamp": context.timestamp,
            "result": result
        })

        return result

    def validate_workflow(self, workflow_id: str) -> Dict:
        """验证工作流配置"""
        # 工作流配置验证逻辑
        return {
            "nodes": ${this.nodes.length},
            "edges": ${this.edges.length},
            "valid": True
        }

    async def get_or_create_agent(
        self,
        workflow_id: str,
        config: Dict
    ) -> "WorkflowAgent":
        """获取或创建 Agent 实例"""
        if workflow_id not in self.agents:
            self.agents[workflow_id] = WorkflowAgent(config)
        return self.agents[workflow_id]

# 执行上下文
class ExecutionContext:
    def __init__(self, workflow_id: str, input_data: Dict, config: Dict, timestamp: datetime):
        self.workflow_id = workflow_id
        self.input_data = input_data
        self.config = config
        self.timestamp = timestamp

# 全局 Agent 管理器实例
agent_manager = AgentManager()`,
    }
  }

  private generateLayer4(): LayeredCode {
    const stateDefinition = this.generateStateDefinition()
    const nodeImplementations = this.generateNodeImplementations()
    const graphConstruction = this.generateGraphConstruction()

    return {
      layer: "Layer 4",
      title: "Agent 执行层 (Agent Execution Layer)",
      description: "预构建Agent、自定义Agent、混合Agent",
      color: "#fff3e0",
      code: `# Layer 4: Agent 执行层
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated, List, Dict, Any
from operator import add
import logging

logger = logging.getLogger(__name__)

${stateDefinition}

${nodeImplementations}

class WorkflowAgent:
    """工作流 Agent 主类"""

    def __init__(self, config: Dict):
        self.config = config
        self.graph = self.build_graph()

    def build_graph(self) -> StateGraph:
        """构建工作流图"""
${graphConstruction}

        return app

    async def run(self, context: ExecutionContext) -> Any:
        """执行工作流"""
        try:
            # 初始化状态
            initial_state = WorkflowState(
                messages=[],
                current_step="",
                input_data=context.input_data,
                output_data={},
                metadata={"workflow_id": context.workflow_id}
            )

            # 运行工作流
            result = await self.graph.ainvoke(initial_state)

            logger.info(f"Workflow completed: {context.workflow_id}")
            return result.get("output_data", {})

        except Exception as e:
            logger.error(f"Workflow execution error: {str(e)}")
            raise`,
    }
  }

  private generateLayer5(): LayeredCode {
    const toolsList = this.generateToolsList()

    return {
      layer: "Layer 5",
      title: "工具与集成层 (Tools & Integration Layer)",
      description: "标准工具、MCP集成模块、工具注册表、外部集成器",
      color: "#fce4ec",
      code: `# Layer 5: 工具与集成层
from langchain.tools import Tool
from typing import List, Dict, Any
import httpx

class ToolManager:
    """工具管理器"""

    def __init__(self):
        self.tools: Dict[str, Tool] = {}
        self.register_builtin_tools()

    def register_builtin_tools(self):
        """注册内置工具"""
${toolsList}

    def get_tool(self, tool_name: str) -> Tool:
        """获取工具实例"""
        if tool_name not in self.tools:
            raise ValueError(f"Tool not found: {tool_name}")
        return self.tools[tool_name]

    def get_all_tools(self) -> List[Tool]:
        """获取所有工具"""
        return list(self.tools.values())

# MCP 集成模块
class MCPIntegration:
    """MCP (Model Context Protocol) 集成"""

    def __init__(self, server_url: str):
        self.server_url = server_url
        self.client = httpx.AsyncClient()

    async def call_mcp_tool(
        self,
        tool_name: str,
        params: Dict[str, Any]
    ) -> Any:
        """调用 MCP 工具"""
        response = await self.client.post(
            f"{self.server_url}/tools/{tool_name}",
            json=params
        )
        return response.json()

# 全局工具管理器
tool_manager = ToolManager()`,
    }
  }

  private generateLayer6(): LayeredCode {
    return {
      layer: "Layer 6",
      title: "基础设施层 (Infrastructure Layer)",
      description: "消息总线、事件路由、任务分发器、配置管理、模型服务、存储服务",
      color: "#f1f8e9",
      code: `# Layer 6: 基础设施层
from typing import Dict, Any, Optional
import os
from pathlib import Path
import json

# 配置管理
class ConfigManager:
    """配置管理器"""

    def __init__(self, config_path: Optional[str] = None):
        self.config_path = config_path or os.getenv("CONFIG_PATH", "config.json")
        self.config = self.load_config()

    def load_config(self) -> Dict[str, Any]:
        """加载配置"""
        if Path(self.config_path).exists():
            with open(self.config_path, 'r') as f:
                return json.load(f)
        return self.get_default_config()

    def get_default_config(self) -> Dict[str, Any]:
        """获取默认配置"""
        return {
            "model": {
                "provider": "openai",
                "model_name": "gpt-4",
                "temperature": 0.7,
                "max_tokens": 2000
            },
            "storage": {
                "type": "local",
                "path": "./data"
            },
            "monitoring": {
                "enabled": True,
                "log_level": "INFO"
            }
        }

# 模型服务
class ModelService:
    """模型服务"""

    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.model = self.initialize_model()

    def initialize_model(self):
        """初始化模型"""
        from langchain_openai import ChatOpenAI

        return ChatOpenAI(
            model=self.config.get("model_name", "gpt-4"),
            temperature=self.config.get("temperature", 0.7),
            max_tokens=self.config.get("max_tokens", 2000)
        )

    async def generate(self, prompt: str) -> str:
        """生成文本"""
        response = await self.model.ainvoke(prompt)
        return response.content

# 存储服务
class StorageService:
    """存储服务"""

    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.storage_path = Path(config.get("path", "./data"))
        self.storage_path.mkdir(parents=True, exist_ok=True)

    async def save(self, key: str, data: Any) -> bool:
        """保存数据"""
        file_path = self.storage_path / f"{key}.json"
        with open(file_path, 'w') as f:
            json.dump(data, f, indent=2)
        return True

    async def load(self, key: str) -> Optional[Any]:
        """加载数据"""
        file_path = self.storage_path / f"{key}.json"
        if file_path.exists():
            with open(file_path, 'r') as f:
                return json.load(f)
        return None

# 监控服务
class MonitoringService:
    """监控服务"""

    def __init__(self, config: Dict[str, Any]):
        self.enabled = config.get("enabled", True)
        self.metrics: Dict[str, Any] = {}

    def track_metric(self, name: str, value: Any):
        """记录指标"""
        if self.enabled:
            self.metrics[name] = value

    def get_metrics(self) -> Dict[str, Any]:
        """获取指标"""
        return self.metrics

# 全局服务实例
config_manager = ConfigManager()
model_service = ModelService(config_manager.config.get("model", {}))
storage_service = StorageService(config_manager.config.get("storage", {}))
monitoring_service = MonitoringService(config_manager.config.get("monitoring", {}))`,
    }
  }

  private generateStateDefinition(): string {
    return `# 工作流状态定义
class WorkflowState(TypedDict):
    """工作流状态"""
    messages: Annotated[List[str], add]  # 消息历史
    current_step: str  # 当前步骤
    input_data: Dict[str, Any]  # 输入数据
    output_data: Dict[str, Any]  # 输出数据
    metadata: Dict[str, Any]  # 元数据`
  }

  private generateNodeImplementations(): string {
    const implementations: string[] = []

    this.nodes.forEach((node) => {
      const config = this.nodeConfigs.get(node.data.type)
      if (!config) return

      const functionName = this.sanitizeFunctionName(node.id)
      const inputParams = config.inputs.map((i) => i.name).join(", ")

      implementations.push(`
async def ${functionName}(state: WorkflowState) -> WorkflowState:
    """${config.label}: ${config.description}"""
    logger.info(f"Executing node: ${node.data.label}")

    # 从状态中获取输入参数
    ${config.inputs.length > 0 ? `# 输入: ${config.inputs.map((i) => i.name).join(", ")}` : "# 无输入参数"}

    # 节点处理逻辑
    try:
        # TODO: 实现具体的节点逻辑
        result = {"status": "completed", "node": "${node.data.label}"}

        # 更新状态
        state["messages"].append(f"Completed: ${node.data.label}")
        state["current_step"] = "${node.id}"
        ${config.outputs.length > 0 ? `state["output_data"]["${functionName}"] = result` : ""}

        return state
    except Exception as e:
        logger.error(f"Node ${node.data.label} failed: {str(e)}")
        raise`)
    })

    return implementations.join("\n")
  }

  private generateGraphConstruction(): string {
    const lines: string[] = []

    lines.push(`        # 创建状态图`)
    lines.push(`        workflow = StateGraph(WorkflowState)`)
    lines.push(`        `)

    lines.push(`        # 添加节点`)
    this.nodes.forEach((node) => {
      const functionName = this.sanitizeFunctionName(node.id)
      lines.push(`        workflow.add_node("${node.id}", ${functionName})`)
    })
    lines.push(`        `)

    if (this.nodes.length > 0) {
      lines.push(`        # 设置入口点`)
      lines.push(`        workflow.set_entry_point("${this.nodes[0].id}")`)
      lines.push(`        `)
    }

    lines.push(`        # 添加边（连接节点）`)
    this.edges.forEach((edge) => {
      lines.push(`        workflow.add_edge("${edge.source}", "${edge.target}")`)
    })
    lines.push(`        `)

    const lastNode = this.nodes[this.nodes.length - 1]
    if (lastNode) {
      lines.push(`        # 连接到结束`)
      lines.push(`        workflow.add_edge("${lastNode.id}", END)`)
      lines.push(`        `)
    }

    lines.push(`        # 编译工作流`)
    lines.push(`        app = workflow.compile()`)

    return lines.join("\n")
  }

  private generateToolsList(): string {
    const toolNodes = this.nodes.filter((node) => {
      const type = node.data.type
      return type === "tool" || type.includes("tool") || type === "http" || type === "api"
    })

    if (toolNodes.length === 0) {
      return `        # 暂无工具节点`
    }

    const tools = toolNodes.map((node) => {
      const toolName = this.sanitizeFunctionName(node.id)
      return `        # ${node.data.label}
        self.tools["${toolName}"] = Tool(
            name="${toolName}",
            description="${node.data.label}",
            func=self.${toolName}_impl
        )`
    })

    return tools.join("\n\n")
  }

  private generateFullCode(layers: LayeredCode[]): string {
    const sections: string[] = []

    sections.push(`"""
${this.generateWorkflowId()} - LangGraph 工作流
自动生成的分层架构代码

节点数量: ${this.nodes.length}
边数量: ${this.edges.length}
生成时间: ${new Date().toISOString()}
"""

`)

    layers.forEach((layer) => {
      sections.push(`# ${"=".repeat(80)}`)
      sections.push(`# ${layer.title}`)
      sections.push(`# ${layer.description}`)
      sections.push(`# ${"=".repeat(80)}`)
      sections.push(``)
      sections.push(layer.code)
      sections.push(``)
      sections.push(``)
    })

    sections.push(`# 主程序入口`)
    sections.push(`if __name__ == "__main__":`)
    sections.push(`    import asyncio`)
    sections.push(`    `)
    sections.push(`    async def main():`)
    sections.push(`        # 创建执行上下文`)
    sections.push(`        context = ExecutionContext(`)
    sections.push(`            workflow_id="${this.generateWorkflowId()}",`)
    sections.push(`            input_data={"query": "测试输入"},`)
    sections.push(`            config={},`)
    sections.push(`            timestamp=datetime.now()`)
    sections.push(`        )`)
    sections.push(`        `)
    sections.push(`        # 执行工作流`)
    sections.push(`        result = await agent_manager.execute(`)
    sections.push(`            workflow_id=context.workflow_id,`)
    sections.push(`            input_data=context.input_data,`)
    sections.push(`            config=context.config`)
    sections.push(`        )`)
    sections.push(`        `)
    sections.push(`        print("Workflow result:", result)`)
    sections.push(`    `)
    sections.push(`    asyncio.run(main())`)

    return sections.join("\n")
  }

  private sanitizeFunctionName(name: string): string {
    return name.replace(/[^a-zA-Z0-9_]/g, "_").replace(/^[0-9]/, "_$&")
  }

  private generateWorkflowId(): string {
    return `workflow_${Date.now()}`
  }
}

/**
 * 便捷函数：生成 LangGraph 代码
 */
export function generateLangGraphCode(
  nodes: Node[],
  edges: Edge[],
  nodeConfigs: NodeConfig[],
): GeneratedLangGraphCode {
  const generator = new LangGraphCodeGenerator(nodes, edges, nodeConfigs)
  return generator.generate()
}
